package com.study.sbsummary.config.database;

import com.study.sbsummary.config.database.shadow.ShadowInterceptor;
import com.study.sbsummary.config.database.shadow.TruelyRoutingDataSource;
import com.study.sbsummary.utils.SqlUtil;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Properties;

/**
 *
 */
@Configuration
@EnableTransactionManagement
@MapperScan(value = ToolsMysqlConfig.SCAN_PACKAGE, sqlSessionFactoryRef = ToolsMysqlConfig.SESSION_FACTORY_BEAN_NAME)
public class ToolsMysqlConfig {

    static final String SCAN_PACKAGE = "com.truely.plog.serving.mapper.tools";
    private static final String DB_TGA = "tools";
    //下面无需修改
    static final String DB_PROPERTIES_NAME = DB_TGA + "Properties";
    static final String SESSION_FACTORY_BEAN_NAME = DB_TGA + "SqlSessionFactory";
    private static final String PROXY_DATASOURCE_BEAN_NAME = "proxy" + DB_TGA + "DataSource";
    private static final String DATASOURCE_BEAN_NAME = DB_TGA + "DataSource";
    private static final String SD_DATASOURCE_BEAN_NAME = "shadow" + DB_TGA + "DataSource";
    public static final String TRANSACTION_MANAGER_BEAN_NAME = DB_TGA + "transactionManager";
    private static final String CONFIGURATION_PREFIX = "spring.datasource.mysql." + DB_TGA;
//	private static final String MAPPER_LOCATIONS = "${" + CONFIGURATION_PREFIX + ".mapperLocations}";

    //    private String mapperLocations = "classpath*:mapper/*.xml";
    private String mapperLocations = "classpath:mapper/tools/*.xml";

    @Autowired
    private ShadowInterceptor shadowInterceptor;

    @Autowired
    private InterceptorConfig interceptorConfig;

    @Autowired
    @Bean(name = DB_PROPERTIES_NAME)
    @ConfigurationProperties(CONFIGURATION_PREFIX)
    public Properties properties() {
        return new Properties();
    }

    @Bean(name = DATASOURCE_BEAN_NAME, destroyMethod = "close")
    @ConfigurationProperties(CONFIGURATION_PREFIX)
    public DataSource mainDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = SD_DATASOURCE_BEAN_NAME, destroyMethod = "close")
    @ConditionalOnBean(ShadowInterceptor.class)
    public DataSource shadowDataSource(@Qualifier(DB_PROPERTIES_NAME) Properties properties) {
        if (shadowInterceptor.isShadowDatabase()) {
            return SqlUtil.shadowDataSource(properties);
        }
        return null;
    }

    @Bean(name = SESSION_FACTORY_BEAN_NAME)
    @ConditionalOnBean({ShadowInterceptor.class, InterceptorConfig.class})
    public SqlSessionFactory toolsSqlSessionFactory(@Qualifier(DATASOURCE_BEAN_NAME) DataSource mainDataSource,
                                                    @Autowired(required = false)@Qualifier(PROXY_DATASOURCE_BEAN_NAME) AbstractRoutingDataSource proxyDataSource)
            throws Exception {
        return SqlUtil.sessionFactory(mainDataSource, proxyDataSource, mapperLocations,
                interceptorConfig.getInterceptors(), shadowInterceptor.isShadowDatabase());
    }

    @Bean("toolsSqlSessionTemplate")
    public SqlSessionTemplate toolsSqlSessionTemplate(
            @Qualifier(SESSION_FACTORY_BEAN_NAME) SqlSessionFactory sessionFactory) {
        return new SqlSessionTemplate(sessionFactory);
    }

    @Bean(name = TRANSACTION_MANAGER_BEAN_NAME)
    @ConditionalOnBean(ShadowInterceptor.class)
    public PlatformTransactionManager transactionManager(@Qualifier(DATASOURCE_BEAN_NAME) DataSource dataSource,
            @Qualifier(PROXY_DATASOURCE_BEAN_NAME) AbstractRoutingDataSource proxyDataSource) {
        if (shadowInterceptor.isShadowDatabase()) {
            return new DataSourceTransactionManager(proxyDataSource);
        }
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = PROXY_DATASOURCE_BEAN_NAME)
    public AbstractRoutingDataSource dataSourceProxy(@Qualifier(DATASOURCE_BEAN_NAME) DataSource mainDataSource,
                                                     @Autowired(required = false)@Qualifier(SD_DATASOURCE_BEAN_NAME) DataSource shadowDataSource) {
        if (shadowInterceptor.isShadowDatabase()) {
            return TruelyRoutingDataSource.proxyDataSource(mainDataSource, shadowDataSource);
        }
        return null;
    }
}
